home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / tcltk / tk8.5 / xmfbox.tcl < prev   
Encoding:
Text File  |  2009-11-17  |  25.3 KB  |  986 lines

  1. # xmfbox.tcl --
  2. #
  3. #    Implements the "Motif" style file selection dialog for the
  4. #    Unix platform. This implementation is used only if the
  5. #    "::tk_strictMotif" flag is set.
  6. #
  7. # RCS: @(#) $Id: xmfbox.tcl,v 1.31.2.1 2009/10/22 10:27:58 dkf Exp $
  8. #
  9. # Copyright (c) 1996 Sun Microsystems, Inc.
  10. # Copyright (c) 1998-2000 Scriptics Corporation
  11. #
  12. # See the file "license.terms" for information on usage and redistribution
  13. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  14.  
  15. namespace eval ::tk::dialog {}
  16. namespace eval ::tk::dialog::file {}
  17.  
  18.  
  19. # ::tk::MotifFDialog --
  20. #
  21. #    Implements a file dialog similar to the standard Motif file
  22. #    selection box.
  23. #
  24. # Arguments:
  25. #    type        "open" or "save"
  26. #    args        Options parsed by the procedure.
  27. #
  28. # Results:
  29. #    When -multiple is set to 0, this returns the absolute pathname
  30. #    of the selected file. (NOTE: This is not the same as a single
  31. #    element list.)
  32. #    When -multiple is set to > 0, this returns a Tcl list of absolute
  33. #       pathnames. The argument for -multiple is ignored, but for consistency
  34. #       with Windows it defines the maximum amount of memory to allocate for
  35. #       the returned filenames.
  36.  
  37. proc ::tk::MotifFDialog {type args} {
  38.     variable ::tk::Priv
  39.     set dataName __tk_filedialog
  40.     upvar ::tk::dialog::file::$dataName data
  41.  
  42.     set w [MotifFDialog_Create $dataName $type $args]
  43.  
  44.     # Set a grab and claim the focus too.
  45.  
  46.     ::tk::SetFocusGrab $w $data(sEnt)
  47.     $data(sEnt) selection range 0 end
  48.  
  49.     # Wait for the user to respond, then restore the focus and
  50.     # return the index of the selected button.  Restore the focus
  51.     # before deleting the window, since otherwise the window manager
  52.     # may take the focus away so we can't redirect it.  Finally,
  53.     # restore any grab that was in effect.
  54.  
  55.     vwait ::tk::Priv(selectFilePath)
  56.     set result $Priv(selectFilePath)
  57.     ::tk::RestoreFocusGrab $w $data(sEnt) withdraw
  58.  
  59.     return $result
  60. }
  61.  
  62. # ::tk::MotifFDialog_Create --
  63. #
  64. #    Creates the Motif file dialog (if it doesn't exist yet) and
  65. #    initialize the internal data structure associated with the
  66. #    dialog.
  67. #
  68. #    This procedure is used by ::tk::MotifFDialog to create the
  69. #    dialog. It's also used by the test suite to test the Motif
  70. #    file dialog implementation. User code shouldn't call this
  71. #    procedure directly.
  72. #
  73. # Arguments:
  74. #    dataName    Name of the global "data" array for the file dialog.
  75. #    type        "Save" or "Open"
  76. #    argList        Options parsed by the procedure.
  77. #
  78. # Results:
  79. #    Pathname of the file dialog.
  80.  
  81. proc ::tk::MotifFDialog_Create {dataName type argList} {
  82.     upvar ::tk::dialog::file::$dataName data
  83.  
  84.     MotifFDialog_Config $dataName $type $argList
  85.  
  86.     if {$data(-parent) eq "."} {
  87.         set w .$dataName
  88.     } else {
  89.         set w $data(-parent).$dataName
  90.     }
  91.  
  92.     # (re)create the dialog box if necessary
  93.     #
  94.     if {![winfo exists $w]} {
  95.     MotifFDialog_BuildUI $w
  96.     } elseif {[winfo class $w] ne "TkMotifFDialog"} {
  97.     destroy $w
  98.     MotifFDialog_BuildUI $w
  99.     } else {
  100.     set data(fEnt) $w.top.f1.ent
  101.     set data(dList) $w.top.f2.a.l
  102.     set data(fList) $w.top.f2.b.l
  103.     set data(sEnt) $w.top.f3.ent
  104.     set data(okBtn) $w.bot.ok
  105.     set data(filterBtn) $w.bot.filter
  106.     set data(cancelBtn) $w.bot.cancel
  107.     }
  108.     MotifFDialog_SetListMode $w
  109.  
  110.     # Dialog boxes should be transient with respect to their parent,
  111.     # so that they will always stay on top of their parent window.  However,
  112.     # some window managers will create the window as withdrawn if the parent
  113.     # window is withdrawn or iconified.  Combined with the grab we put on the
  114.     # window, this can hang the entire application.  Therefore we only make
  115.     # the dialog transient if the parent is viewable.
  116.  
  117.     if {[winfo viewable [winfo toplevel $data(-parent)]] } {
  118.     wm transient $w $data(-parent)
  119.     }
  120.  
  121.     MotifFDialog_FileTypes $w
  122.     MotifFDialog_Update $w
  123.  
  124.     # Withdraw the window, then update all the geometry information
  125.     # so we know how big it wants to be, then center the window in the
  126.     # display (Motif style) and de-iconify it.
  127.  
  128.     ::tk::PlaceWindow $w
  129.     wm title $w $data(-title)
  130.  
  131.     return $w
  132. }
  133.  
  134. # ::tk::MotifFDialog_FileTypes --
  135. #
  136. #    Checks the -filetypes option. If present this adds a list of radio-
  137. #    buttons to pick the file types from.
  138. #
  139. # Arguments:
  140. #    w        Pathname of the tk_get*File dialogue.
  141. #
  142. # Results:
  143. #    none
  144.  
  145. proc ::tk::MotifFDialog_FileTypes {w} {
  146.     upvar ::tk::dialog::file::[winfo name $w] data
  147.  
  148.     set f $w.top.f3.types
  149.     destroy $f
  150.  
  151.     # No file types: use "*" as the filter and display no radio-buttons
  152.     if {$data(-filetypes) eq ""} {
  153.     set data(filter) *
  154.     return
  155.     }
  156.  
  157.     # The filetypes radiobuttons
  158.     # set data(fileType) $data(-defaulttype)
  159.     # Default type to first entry
  160.     set initialTypeName [lindex $data(-filetypes) 0 0]
  161.     if {$data(-typevariable) ne ""} {
  162.     upvar #0 $data(-typevariable) typeVariable
  163.     if {[info exist typeVariable]} {
  164.         set initialTypeName $typeVariable
  165.     }
  166.     }
  167.     set ix 0
  168.     set data(fileType) 0
  169.     foreach fltr $data(-filetypes) {
  170.     set fname [lindex $fltr 0]
  171.     if {[string first $initialTypeName $fname] == 0} {
  172.         set data(fileType) $ix
  173.         break
  174.     }
  175.     incr ix
  176.     }
  177.  
  178.     MotifFDialog_SetFilter $w [lindex $data(-filetypes) $data(fileType)]
  179.  
  180.     #don't produce radiobuttons for only one filetype
  181.     if {[llength $data(-filetypes)] == 1} {
  182.     return
  183.     }
  184.  
  185.     frame $f
  186.     set cnt 0
  187.     if {$data(-filetypes) ne {}} {
  188.     foreach type $data(-filetypes) {
  189.         set title  [lindex [lindex $type 0] 0]
  190.         set filter [lindex $type 1]
  191.         radiobutton $f.b$cnt \
  192.         -text $title \
  193.         -variable ::tk::dialog::file::[winfo name $w](fileType) \
  194.         -value $cnt \
  195.         -command [list tk::MotifFDialog_SetFilter $w $type]
  196.         pack $f.b$cnt -side left
  197.         incr cnt
  198.     }
  199.     }
  200.     $f.b$data(fileType) invoke
  201.  
  202.     pack $f -side bottom -fill both
  203.  
  204.     return
  205. }
  206.  
  207. # This proc gets called whenever data(filter) is set
  208. #
  209. proc ::tk::MotifFDialog_SetFilter {w type} {
  210.     upvar ::tk::dialog::file::[winfo name $w] data
  211.     variable ::tk::Priv
  212.  
  213.     set data(filter) [lindex $type 1]
  214.     set Priv(selectFileType) [lindex [lindex $type 0] 0]
  215.  
  216.     MotifFDialog_Update $w
  217. }
  218.  
  219. # ::tk::MotifFDialog_Config --
  220. #
  221. #    Iterates over the optional arguments to determine the option
  222. #    values for the Motif file dialog; gives default values to
  223. #    unspecified options.
  224. #
  225. # Arguments:
  226. #    dataName    The name of the global variable in which
  227. #            data for the file dialog is stored.
  228. #    type        "Save" or "Open"
  229. #    argList        Options parsed by the procedure.
  230.  
  231. proc ::tk::MotifFDialog_Config {dataName type argList} {
  232.     upvar ::tk::dialog::file::$dataName data
  233.  
  234.     set data(type) $type
  235.  
  236.     # 1: the configuration specs
  237.     #
  238.     set specs {
  239.     {-defaultextension "" "" ""}
  240.     {-filetypes "" "" ""}
  241.     {-initialdir "" "" ""}
  242.     {-initialfile "" "" ""}
  243.     {-parent "" "" "."}
  244.     {-title "" "" ""}
  245.     {-typevariable "" "" ""}
  246.     }
  247.     if {$type eq "open"} {
  248.     lappend specs {-multiple "" "" "0"}
  249.     }
  250.  
  251.     set data(-multiple) 0
  252.     # 2: default values depending on the type of the dialog
  253.     #
  254.     if {![info exists data(selectPath)]} {
  255.     # first time the dialog has been popped up
  256.     set data(selectPath) [pwd]
  257.     set data(selectFile) ""
  258.     }
  259.  
  260.     # 3: parse the arguments
  261.     #
  262.     tclParseConfigSpec ::tk::dialog::file::$dataName $specs "" $argList
  263.  
  264.     if {$data(-title) eq ""} {
  265.     if {$type eq "open"} {
  266.         if {$data(-multiple) != 0} {
  267.         set data(-title) "[mc {Open Multiple Files}]"
  268.         } else {
  269.         set data(-title) [mc "Open"]
  270.         }
  271.     } else {
  272.         set data(-title) [mc "Save As"]
  273.     }
  274.     }
  275.  
  276.     # 4: set the default directory and selection according to the -initial
  277.     #    settings
  278.     #
  279.     if {$data(-initialdir) ne ""} {
  280.     if {[file isdirectory $data(-initialdir)]} {
  281.         set data(selectPath) [lindex [glob $data(-initialdir)] 0]
  282.     } else {
  283.         set data(selectPath) [pwd]
  284.     }
  285.  
  286.     # Convert the initialdir to an absolute path name.
  287.  
  288.     set old [pwd]
  289.     cd $data(selectPath)
  290.     set data(selectPath) [pwd]
  291.     cd $old
  292.     }
  293.     set data(selectFile) $data(-initialfile)
  294.  
  295.     # 5. Parse the -filetypes option. It is not used by the motif
  296.     #    file dialog, but we check for validity of the value to make sure
  297.     #    the application code also runs fine with the TK file dialog.
  298.     #
  299.     set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)]
  300.  
  301.     if {![info exists data(filter)]} {
  302.     set data(filter) *
  303.     }
  304.     if {![winfo exists $data(-parent)]} {
  305.     error "bad window path name \"$data(-parent)\""
  306.     }
  307. }
  308.  
  309. # ::tk::MotifFDialog_BuildUI --
  310. #
  311. #    Builds the UI components of the Motif file dialog.
  312. #
  313. # Arguments:
  314. #     w        Pathname of the dialog to build.
  315. #
  316. # Results:
  317. #     None.
  318.  
  319. proc ::tk::MotifFDialog_BuildUI {w} {
  320.     set dataName [lindex [split $w .] end]
  321.     upvar ::tk::dialog::file::$dataName data
  322.  
  323.     # Create the dialog toplevel and internal frames.
  324.     #
  325.     toplevel $w -class TkMotifFDialog
  326.     set top [frame $w.top -relief raised -bd 1]
  327.     set bot [frame $w.bot -relief raised -bd 1]
  328.  
  329.     pack $w.bot -side bottom -fill x
  330.     pack $w.top -side top -expand yes -fill both
  331.  
  332.     set f1 [frame $top.f1]
  333.     set f2 [frame $top.f2]
  334.     set f3 [frame $top.f3]
  335.  
  336.     pack $f1 -side top    -fill x
  337.     pack $f3 -side bottom -fill x
  338.     pack $f2 -expand yes -fill both
  339.  
  340.     set f2a [frame $f2.a]
  341.     set f2b [frame $f2.b]
  342.  
  343.     grid $f2a -row 0 -column 0 -rowspan 1 -columnspan 1 -padx 4 -pady 4 \
  344.     -sticky news
  345.     grid $f2b -row 0 -column 1 -rowspan 1 -columnspan 1 -padx 4 -pady 4 \
  346.     -sticky news
  347.     grid rowconfigure $f2 0    -minsize 0   -weight 1
  348.     grid columnconfigure $f2 0 -minsize 0   -weight 1
  349.     grid columnconfigure $f2 1 -minsize 150 -weight 2
  350.  
  351.     # The Filter box
  352.     #
  353.     bind [::tk::AmpWidget label $f1.lab -text [mc "Fil&ter:"] -anchor w] \
  354.     <<AltUnderlined>> [list focus $f1.ent]
  355.     entry $f1.ent
  356.     pack $f1.lab -side top -fill x -padx 6 -pady 4
  357.     pack $f1.ent -side top -fill x -padx 4 -pady 0
  358.     set data(fEnt) $f1.ent
  359.  
  360.     # The file and directory lists
  361.     #
  362.     set data(dList) [MotifFDialog_MakeSList $w $f2a \
  363.         [mc "&Directory:"] DList]
  364.     set data(fList) [MotifFDialog_MakeSList $w $f2b \
  365.         [mc "Fi&les:"]     FList]
  366.  
  367.     # The Selection box
  368.     #
  369.     bind [::tk::AmpWidget label $f3.lab -text [mc "&Selection:"] -anchor w] \
  370.     <<AltUnderlined>> [list focus $f3.ent]
  371.     entry $f3.ent
  372.     pack $f3.lab -side top -fill x -padx 6 -pady 0
  373.     pack $f3.ent -side top -fill x -padx 4 -pady 4
  374.     set data(sEnt) $f3.ent
  375.  
  376.     # The buttons
  377.     #
  378.     set maxWidth [::tk::mcmaxamp &OK &Filter &Cancel]
  379.     set maxWidth [expr {$maxWidth<6?6:$maxWidth}]
  380.     set data(okBtn) [::tk::AmpWidget button $bot.ok -text [mc "&OK"] \
  381.         -width $maxWidth \
  382.         -command [list tk::MotifFDialog_OkCmd $w]]
  383.     set data(filterBtn) [::tk::AmpWidget button $bot.filter -text [mc "&Filter"] \
  384.         -width $maxWidth \
  385.         -command [list tk::MotifFDialog_FilterCmd $w]]
  386.     set data(cancelBtn) [::tk::AmpWidget button $bot.cancel -text [mc "&Cancel"] \
  387.         -width $maxWidth \
  388.         -command [list tk::MotifFDialog_CancelCmd $w]]
  389.  
  390.     pack $bot.ok $bot.filter $bot.cancel -padx 10 -pady 10 -expand yes \
  391.     -side left
  392.  
  393.     # Create the bindings:
  394.     #
  395.     bind $w <Alt-Key> [list ::tk::AltKeyInDialog $w %A]
  396.  
  397.     bind $data(fEnt) <Return> [list tk::MotifFDialog_ActivateFEnt $w]
  398.     bind $data(sEnt) <Return> [list tk::MotifFDialog_ActivateSEnt $w]
  399.     bind $w <Escape> [list tk::MotifFDialog_CancelCmd $w]
  400.     bind $w.bot <Destroy> {set ::tk::Priv(selectFilePath) {}}
  401.  
  402.     wm protocol $w WM_DELETE_WINDOW [list tk::MotifFDialog_CancelCmd $w]
  403. }
  404.  
  405. proc ::tk::MotifFDialog_SetListMode {w} {
  406.     upvar ::tk::dialog::file::[winfo name $w] data
  407.  
  408.     if {$data(-multiple) != 0} {
  409.     set selectmode extended
  410.     } else {
  411.     set selectmode browse
  412.     }
  413.     set f $w.top.f2.b
  414.     $f.l configure -selectmode $selectmode
  415. }
  416.  
  417. # ::tk::MotifFDialog_MakeSList --
  418. #
  419. #    Create a scrolled-listbox and set the keyboard accelerator
  420. #    bindings so that the list selection follows what the user
  421. #    types.
  422. #
  423. # Arguments:
  424. #    w        Pathname of the dialog box.
  425. #    f        Frame widget inside which to create the scrolled
  426. #            listbox. This frame widget already exists.
  427. #    label        The string to display on top of the listbox.
  428. #    under        Sets the -under option of the label.
  429. #    cmdPrefix    Specifies procedures to call when the listbox is
  430. #            browsed or activated.
  431.  
  432. proc ::tk::MotifFDialog_MakeSList {w f label cmdPrefix} {
  433.     bind [::tk::AmpWidget label $f.lab -text $label -anchor w] \
  434.     <<AltUnderlined>> [list focus $f.l]
  435.     listbox $f.l -width 12 -height 5 -exportselection 0\
  436.     -xscrollcommand [list $f.h set]    -yscrollcommand [list $f.v set]
  437.     scrollbar $f.v -orient vertical   -takefocus 0 -command [list $f.l yview]
  438.     scrollbar $f.h -orient horizontal -takefocus 0 -command [list $f.l xview]
  439.     grid $f.lab -row 0 -column 0 -sticky news -rowspan 1 -columnspan 2 \
  440.     -padx 2 -pady 2
  441.     grid $f.l -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
  442.     grid $f.v -row 1 -column 1 -rowspan 1 -columnspan 1 -sticky news
  443.     grid $f.h -row 2 -column 0 -rowspan 1 -columnspan 1 -sticky news
  444.  
  445.     grid rowconfigure    $f 0 -weight 0 -minsize 0
  446.     grid rowconfigure    $f 1 -weight 1 -minsize 0
  447.     grid columnconfigure $f 0 -weight 1 -minsize 0
  448.  
  449.     # bindings for the listboxes
  450.     #
  451.     set list $f.l
  452.     bind $list <<ListboxSelect>> [list tk::MotifFDialog_Browse$cmdPrefix $w]
  453.     bind $list <Double-ButtonRelease-1> \
  454.         [list tk::MotifFDialog_Activate$cmdPrefix $w]
  455.     bind $list <Return>    "tk::MotifFDialog_Browse$cmdPrefix [list $w]; \
  456.         tk::MotifFDialog_Activate$cmdPrefix [list $w]"
  457.  
  458.     bindtags $list [list Listbox $list [winfo toplevel $list] all]
  459.     ListBoxKeyAccel_Set $list
  460.  
  461.     return $f.l
  462. }
  463.  
  464. # ::tk::MotifFDialog_InterpFilter --
  465. #
  466. #    Interpret the string in the filter entry into two components:
  467. #    the directory and the pattern. If the string is a relative
  468. #    pathname, give a warning to the user and restore the pattern
  469. #    to original.
  470. #
  471. # Arguments:
  472. #    w        pathname of the dialog box.
  473. #
  474. # Results:
  475. #     A list of two elements. The first element is the directory
  476. #     specified # by the filter. The second element is the filter
  477. #     pattern itself.
  478.  
  479. proc ::tk::MotifFDialog_InterpFilter {w} {
  480.     upvar ::tk::dialog::file::[winfo name $w] data
  481.  
  482.     set text [string trim [$data(fEnt) get]]
  483.  
  484.     # Perform tilde substitution
  485.     #
  486.     set badTilde 0
  487.     if {[string index $text 0] eq "~"} {
  488.     set list [file split $text]
  489.     set tilde [lindex $list 0]
  490.     if {[catch {set tilde [glob $tilde]}]} {
  491.         set badTilde 1
  492.     } else {
  493.         set text [eval file join [concat $tilde [lrange $list 1 end]]]
  494.     }
  495.     }
  496.  
  497.     # If the string is a relative pathname, combine it
  498.     # with the current selectPath.
  499.  
  500.     set relative 0
  501.     if {[file pathtype $text] eq "relative"} {
  502.     set relative 1
  503.     } elseif {$badTilde} {
  504.     set relative 1    
  505.     }
  506.  
  507.     if {$relative} {
  508.     tk_messageBox -icon warning -type ok \
  509.         -message "\"$text\" must be an absolute pathname"
  510.  
  511.     $data(fEnt) delete 0 end
  512.     $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
  513.         $data(filter)]
  514.  
  515.     return [list $data(selectPath) $data(filter)]
  516.     }
  517.  
  518.     set resolved [::tk::dialog::file::JoinFile [file dirname $text] [file tail $text]]
  519.  
  520.     if {[file isdirectory $resolved]} {
  521.     set dir $resolved
  522.     set fil $data(filter)
  523.     } else {
  524.     set dir [file dirname $resolved]
  525.     set fil [file tail    $resolved]
  526.     }
  527.  
  528.     return [list $dir $fil]
  529. }
  530.  
  531. # ::tk::MotifFDialog_Update
  532. #
  533. #    Load the files and synchronize the "filter" and "selection" fields
  534. #    boxes.
  535. #
  536. # Arguments:
  537. #     w         pathname of the dialog box.
  538. #
  539. # Results:
  540. #    None.
  541.  
  542. proc ::tk::MotifFDialog_Update {w} {
  543.     upvar ::tk::dialog::file::[winfo name $w] data
  544.  
  545.     $data(fEnt) delete 0 end
  546.     $data(fEnt) insert 0 \
  547.             [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]
  548.     $data(sEnt) delete 0 end
  549.     $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
  550.         $data(selectFile)]
  551.  
  552.     MotifFDialog_LoadFiles $w
  553. }
  554.  
  555. # ::tk::MotifFDialog_LoadFiles --
  556. #
  557. #    Loads the files and directories into the two listboxes according
  558. #    to the filter setting.
  559. #
  560. # Arguments:
  561. #     w         pathname of the dialog box.
  562. #
  563. # Results:
  564. #    None.
  565.  
  566. proc ::tk::MotifFDialog_LoadFiles {w} {
  567.     upvar ::tk::dialog::file::[winfo name $w] data
  568.  
  569.     $data(dList) delete 0 end
  570.     $data(fList) delete 0 end
  571.  
  572.     set appPWD [pwd]
  573.     if {[catch {cd $data(selectPath)}]} {
  574.     cd $appPWD
  575.  
  576.     $data(dList) insert end ".."
  577.     return
  578.     }
  579.  
  580.     # Make the dir and file lists
  581.     #
  582.     # For speed we only have one glob, which reduces the file system
  583.     # calls (good for slow NFS networks).
  584.     #
  585.     # We also do two smaller sorts (files + dirs) instead of one large sort,
  586.     # which gives a small speed increase.
  587.     #
  588.     set top 0
  589.     set dlist ""
  590.     set flist ""
  591.     foreach f [glob -nocomplain .* *] {
  592.     if {[file isdir ./$f]} {
  593.         lappend dlist $f
  594.     } else {
  595.             foreach pat $data(filter) {
  596.                 if {[string match $pat $f]} {
  597.             if {[string match .* $f]} {
  598.             incr top
  599.             }
  600.             lappend flist $f
  601.                     break
  602.         }
  603.             }
  604.     }
  605.     }
  606.     eval [list $data(dList) insert end] [lsort -dictionary $dlist]
  607.     eval [list $data(fList) insert end] [lsort -dictionary $flist]
  608.  
  609.     # The user probably doesn't want to see the . files. We adjust the view
  610.     # so that the listbox displays all the non-dot files
  611.     $data(fList) yview $top
  612.  
  613.     cd $appPWD
  614. }
  615.  
  616. # ::tk::MotifFDialog_BrowseDList --
  617. #
  618. #    This procedure is called when the directory list is browsed
  619. #    (clicked-over) by the user.
  620. #
  621. # Arguments:
  622. #     w        The pathname of the dialog box.
  623. #
  624. # Results:
  625. #    None.    
  626.  
  627. proc ::tk::MotifFDialog_BrowseDList {w} {
  628.     upvar ::tk::dialog::file::[winfo name $w] data
  629.  
  630.     focus $data(dList)
  631.     if {[$data(dList) curselection] eq ""} {
  632.     return
  633.     }
  634.     set subdir [$data(dList) get [$data(dList) curselection]]
  635.     if {$subdir eq ""} {
  636.     return
  637.     }
  638.  
  639.     $data(fList) selection clear 0 end
  640.  
  641.     set list [MotifFDialog_InterpFilter $w]
  642.     set data(filter) [lindex $list 1]
  643.  
  644.     switch -- $subdir {
  645.     . {
  646.         set newSpec [::tk::dialog::file::JoinFile $data(selectPath) $data(filter)]
  647.     }
  648.     .. {
  649.         set newSpec [::tk::dialog::file::JoinFile [file dirname $data(selectPath)] \
  650.         $data(filter)]
  651.     }
  652.     default {
  653.         set newSpec [::tk::dialog::file::JoinFile [::tk::dialog::file::JoinFile \
  654.             $data(selectPath) $subdir] $data(filter)]
  655.     }
  656.     }
  657.  
  658.     $data(fEnt) delete 0 end
  659.     $data(fEnt) insert 0 $newSpec
  660. }
  661.  
  662. # ::tk::MotifFDialog_ActivateDList --
  663. #
  664. #    This procedure is called when the directory list is activated
  665. #    (double-clicked) by the user.
  666. #
  667. # Arguments:
  668. #     w        The pathname of the dialog box.
  669. #
  670. # Results:
  671. #    None.    
  672.  
  673. proc ::tk::MotifFDialog_ActivateDList {w} {
  674.     upvar ::tk::dialog::file::[winfo name $w] data
  675.  
  676.     if {[$data(dList) curselection] eq ""} {
  677.     return
  678.     }
  679.     set subdir [$data(dList) get [$data(dList) curselection]]
  680.     if {$subdir eq ""} {
  681.     return
  682.     }
  683.  
  684.     $data(fList) selection clear 0 end
  685.  
  686.     switch -- $subdir {
  687.     . {
  688.         set newDir $data(selectPath)
  689.     }
  690.     .. {
  691.         set newDir [file dirname $data(selectPath)]
  692.     }
  693.     default {
  694.         set newDir [::tk::dialog::file::JoinFile $data(selectPath) $subdir]
  695.     }
  696.     }
  697.  
  698.     set data(selectPath) $newDir
  699.     MotifFDialog_Update $w
  700.  
  701.     if {$subdir ne ".."} {
  702.     $data(dList) selection set 0
  703.     $data(dList) activate 0
  704.     } else {
  705.     $data(dList) selection set 1
  706.     $data(dList) activate 1
  707.     }
  708. }
  709.  
  710. # ::tk::MotifFDialog_BrowseFList --
  711. #
  712. #    This procedure is called when the file list is browsed
  713. #    (clicked-over) by the user.
  714. #
  715. # Arguments:
  716. #     w        The pathname of the dialog box.
  717. #
  718. # Results:
  719. #    None.    
  720.  
  721. proc ::tk::MotifFDialog_BrowseFList {w} {
  722.     upvar ::tk::dialog::file::[winfo name $w] data
  723.  
  724.     focus $data(fList)
  725.     set data(selectFile) ""
  726.     foreach item [$data(fList) curselection] {
  727.     lappend data(selectFile) [$data(fList) get $item]
  728.     }
  729.     if {[llength $data(selectFile)] == 0} {
  730.     return
  731.     }
  732.  
  733.     $data(dList) selection clear 0 end
  734.  
  735.     $data(fEnt) delete 0 end
  736.     $data(fEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
  737.         $data(filter)]
  738.     $data(fEnt) xview end
  739.  
  740.     # if it's a multiple selection box, just put in the filenames 
  741.     # otherwise put in the full path as usual 
  742.     $data(sEnt) delete 0 end
  743.     if {$data(-multiple) != 0} {
  744.     $data(sEnt) insert 0 $data(selectFile)
  745.     } else {
  746.     $data(sEnt) insert 0 [::tk::dialog::file::JoinFile $data(selectPath) \
  747.         [lindex $data(selectFile) 0]]
  748.     }
  749.     $data(sEnt) xview end
  750. }
  751.  
  752. # ::tk::MotifFDialog_ActivateFList --
  753. #
  754. #    This procedure is called when the file list is activated
  755. #    (double-clicked) by the user.
  756. #
  757. # Arguments:
  758. #     w        The pathname of the dialog box.
  759. #
  760. # Results:
  761. #    None.    
  762.  
  763. proc ::tk::MotifFDialog_ActivateFList {w} {
  764.     upvar ::tk::dialog::file::[winfo name $w] data
  765.  
  766.     if {[$data(fList) curselection] eq ""} {
  767.     return
  768.     }
  769.     set data(selectFile) [$data(fList) get [$data(fList) curselection]]
  770.     if {$data(selectFile) eq ""} {
  771.     return
  772.     } else {
  773.     MotifFDialog_ActivateSEnt $w
  774.     }
  775. }
  776.  
  777. # ::tk::MotifFDialog_ActivateFEnt --
  778. #
  779. #    This procedure is called when the user presses Return inside
  780. #    the "filter" entry. It updates the dialog according to the
  781. #    text inside the filter entry.
  782. #
  783. # Arguments:
  784. #     w        The pathname of the dialog box.
  785. #
  786. # Results:
  787. #    None.    
  788.  
  789. proc ::tk::MotifFDialog_ActivateFEnt {w} {
  790.     upvar ::tk::dialog::file::[winfo name $w] data
  791.  
  792.     set list [MotifFDialog_InterpFilter $w]
  793.     set data(selectPath) [lindex $list 0]
  794.     set data(filter)    [lindex $list 1]
  795.  
  796.     MotifFDialog_Update $w
  797. }
  798.  
  799. # ::tk::MotifFDialog_ActivateSEnt --
  800. #
  801. #    This procedure is called when the user presses Return inside
  802. #    the "selection" entry. It sets the ::tk::Priv(selectFilePath) 
  803. #    variable so that the vwait loop in tk::MotifFDialog will be
  804. #    terminated.
  805. #
  806. # Arguments:
  807. #     w        The pathname of the dialog box.
  808. #
  809. # Results:
  810. #    None.    
  811.  
  812. proc ::tk::MotifFDialog_ActivateSEnt {w} {
  813.     variable ::tk::Priv
  814.     upvar ::tk::dialog::file::[winfo name $w] data
  815.  
  816.     set selectFilePath [string trim [$data(sEnt) get]]
  817.  
  818.     if {$selectFilePath eq ""} {
  819.     MotifFDialog_FilterCmd $w
  820.     return
  821.     }
  822.  
  823.     if {$data(-multiple) == 0} {
  824.     set selectFilePath [list $selectFilePath]
  825.     }
  826.  
  827.     if {[file isdirectory [lindex $selectFilePath 0]]} {
  828.     set data(selectPath) [lindex [glob $selectFilePath] 0]
  829.     set data(selectFile) ""
  830.     MotifFDialog_Update $w
  831.     return
  832.     }
  833.  
  834.     set newFileList ""
  835.     foreach item $selectFilePath {
  836.     if {[file pathtype $item] ne "absolute"} {
  837.         set item [file join $data(selectPath) $item]
  838.     } elseif {![file exists [file dirname $item]]} {
  839.         tk_messageBox -icon warning -type ok \
  840.             -message [mc {Directory "%1$s" does not exist.} \
  841.             [file dirname $item]]
  842.         return
  843.     }
  844.  
  845.     if {![file exists $item]} {
  846.         if {$data(type) eq "open"} {
  847.         tk_messageBox -icon warning -type ok \
  848.             -message [mc {File "%1$s" does not exist.} $item]
  849.         return
  850.         }
  851.     } elseif {$data(type) eq "save"} {
  852.         set message [format %s%s \
  853.             [mc "File \"%1\$s\" already exists.\n\n" $selectFilePath] \
  854.             [mc {Replace existing file?}]]
  855.         set answer [tk_messageBox -icon warning -type yesno \
  856.             -message $message]
  857.         if {$answer eq "no"} {
  858.         return
  859.         }
  860.     }
  861.  
  862.     lappend newFileList $item
  863.     }
  864.  
  865.     # Return selected filter
  866.     if {[info exists data(-typevariable)] && $data(-typevariable) ne ""
  867.         && [info exists data(-filetypes)] && $data(-filetypes) ne ""} {
  868.     upvar #0 $data(-typevariable) typeVariable
  869.     set typeVariable [lindex $data(-filetypes) $data(fileType) 0]
  870.     }
  871.  
  872.     if {$data(-multiple) != 0} {
  873.     set Priv(selectFilePath) $newFileList
  874.     } else {
  875.     set Priv(selectFilePath) [lindex $newFileList 0]
  876.     }
  877.  
  878.     # Set selectFile and selectPath to first item in list
  879.     set Priv(selectFile)     [file tail    [lindex $newFileList 0]]
  880.     set Priv(selectPath)     [file dirname [lindex $newFileList 0]]
  881. }
  882.  
  883.  
  884. proc ::tk::MotifFDialog_OkCmd {w} {
  885.     upvar ::tk::dialog::file::[winfo name $w] data
  886.  
  887.     MotifFDialog_ActivateSEnt $w
  888. }
  889.  
  890. proc ::tk::MotifFDialog_FilterCmd {w} {
  891.     upvar ::tk::dialog::file::[winfo name $w] data
  892.  
  893.     MotifFDialog_ActivateFEnt $w
  894. }
  895.  
  896. proc ::tk::MotifFDialog_CancelCmd {w} {
  897.     variable ::tk::Priv
  898.  
  899.     set Priv(selectFilePath) ""
  900.     set Priv(selectFile)     ""
  901.     set Priv(selectPath)     ""
  902. }
  903.  
  904. proc ::tk::ListBoxKeyAccel_Set {w} {
  905.     bind Listbox <Any-KeyPress> ""
  906.     bind $w <Destroy> [list tk::ListBoxKeyAccel_Unset $w]
  907.     bind $w <Any-KeyPress> [list tk::ListBoxKeyAccel_Key $w %A]
  908. }
  909.  
  910. proc ::tk::ListBoxKeyAccel_Unset {w} {
  911.     variable ::tk::Priv
  912.  
  913.     catch {after cancel $Priv(lbAccel,$w,afterId)}
  914.     unset -nocomplain Priv(lbAccel,$w) Priv(lbAccel,$w,afterId)
  915. }
  916.  
  917. # ::tk::ListBoxKeyAccel_Key--
  918. #
  919. #    This procedure maintains a list of recently entered keystrokes
  920. #    over a listbox widget. It arranges an idle event to move the
  921. #    selection of the listbox to the entry that begins with the
  922. #    keystrokes.
  923. #
  924. # Arguments:
  925. #     w        The pathname of the listbox.
  926. #    key        The key which the user just pressed.
  927. #
  928. # Results:
  929. #    None.    
  930.  
  931. proc ::tk::ListBoxKeyAccel_Key {w key} {
  932.     variable ::tk::Priv
  933.  
  934.     if { $key eq "" } {
  935.     return
  936.     }
  937.     append Priv(lbAccel,$w) $key
  938.     ListBoxKeyAccel_Goto $w $Priv(lbAccel,$w)
  939.     catch {
  940.     after cancel $Priv(lbAccel,$w,afterId)
  941.     }
  942.     set Priv(lbAccel,$w,afterId) [after 500 \
  943.         [list tk::ListBoxKeyAccel_Reset $w]]
  944. }
  945.  
  946. proc ::tk::ListBoxKeyAccel_Goto {w string} {
  947.     variable ::tk::Priv
  948.  
  949.     set string [string tolower $string]
  950.     set end [$w index end]
  951.     set theIndex -1
  952.  
  953.     for {set i 0} {$i < $end} {incr i} {
  954.     set item [string tolower [$w get $i]]
  955.     if {[string compare $string $item] >= 0} {
  956.         set theIndex $i
  957.     }
  958.     if {[string compare $string $item] <= 0} {
  959.         set theIndex $i
  960.         break
  961.     }
  962.     }
  963.  
  964.     if {$theIndex >= 0} {
  965.     $w selection clear 0 end
  966.     $w selection set $theIndex $theIndex
  967.     $w activate $theIndex
  968.     $w see $theIndex
  969.     event generate $w <<ListboxSelect>>
  970.     }
  971. }
  972.  
  973. proc ::tk::ListBoxKeyAccel_Reset {w} {
  974.     variable ::tk::Priv
  975.  
  976.     unset -nocomplain Priv(lbAccel,$w)
  977. }
  978.  
  979. proc ::tk_getFileType {} {
  980.     variable ::tk::Priv
  981.  
  982.     return $Priv(selectFileType)
  983. }
  984.  
  985.